// SPDX-License-Identifier: GPL-2.0
/* Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved. */

#include "e1000_led.h"
#include "e1000_hw.h"
#include "e1000_regs.h"

s32 igb_ctrl_led_generic(struct e1000_hw *hw, s32 led_id, s32 mode)
{
	u32 ledctl = 0;
	u32 shift[] = {E1000_LEDCTL_LED0_MODE_SHIFT, E1000_LEDCTL_LED1_MODE_SHIFT,
				   E1000_LEDCTL_LED2_MODE_SHIFT};

	if (led_id >= E1000_LED_NUM || led_id < 0) {
		hw_dbg("igb ctl led id %d is invalid.", led_id);
		return E1000_ERR_INVM_VALUE_NOT_FOUND;
	}

	ledctl = igb_rd32(hw, E1000_LEDCTL);
	hw_dbg("igb ctl led id %d, mode %d, ledctl 0x%x.\n", led_id, mode, ledctl);

	switch (mode) {
	case LED_MODE_LINK_ON:
		ledctl &= (~(E1000_LEDCTL_LED0_ALL << shift[led_id]));
		ledctl |= (E1000_LEDCTL_LED0_LINKUP << shift[led_id]);
		break;
	case LED_MODE_ACT_BLINK:
		ledctl &= (~(E1000_LEDCTL_LED0_ALL << shift[led_id]));
		ledctl |= (E1000_LEDCTL_LED0_ACT << shift[led_id]);
		break;
	case LED_MODE_LINK_ON_ACT_BLINK:
		ledctl &= (~(E1000_LEDCTL_LED0_ALL << shift[led_id]));
		ledctl |= (E1000_LEDCTL_LED0_ACT_LINKUP << shift[led_id]);
		break;
	case LED_MODE_FORECE_OFF:
		ledctl &= (~((E1000_LEDCTL_LED0_IVRT | E1000_LEDCTL_LED0_BLINK) << shift[led_id]));
		ledctl |= (E1000_LEDCTL_MODE_LED_OFF << shift[led_id]);
		break;
	case LED_MODE_FORCE_ON:
		ledctl &= (~(E1000_LEDCTL_LED0_BLINK << shift[led_id]));
		ledctl |= ((E1000_LEDCTL_LED0_IVRT | E1000_LEDCTL_MODE_LED_ON) << shift[led_id]);
		break;
	case LED_MODE_FORECE_BLINK:
		ledctl |= ((E1000_LEDCTL_LED0_BLINK | E1000_LEDCTL_MODE_LED_ON) << shift[led_id]);
		break;
	default:
		return E1000_ERR_INVM_VALUE_NOT_FOUND;
	}

	wr32(E1000_LEDCTL, ledctl);

	return 0;
}
EXPORT_SYMBOL(igb_ctrl_led_generic);
